/**
 * Copyright (c) 2006-2020, zwl
 * 
 * description
 * 
 * Change Logs:
 * Date             Author         Notes
 * 
 * 
 */
#include "EntTypeFramework.h"

static clock_time_t                         etf_clock_count             = 0;
static clock_time_t                         etf_next_expiration         = 0;
static etf_uint8_t                          etf_timer_run_flag          = 0;
static struct etf_object_information *      timer_information           = ETF_NULL;

/**
 * 定时器模块初始化
 *
 *@param :
 *
 *@return:
 *
 *@note  : 
 *
 *
 */
void etf_timer_module_init(void){
    timer_information                                                   = etf_object_get_information(ETF_Object_Class_Timer);
    ETF_IN_ASSERT(ETF_NULL != timer_information);
}

/**
 * 心跳时钟处理函数
 *
 *@param :
 *
 *@return:
 *
 *@note  : 
 * 
 *
 */
void etf_timer_clock(void){

    if(ETF_NULL != timer_information){
        /* 心跳时钟计数 */
        etf_clock_count++;
        
        if( !etf_list_isempty(&(timer_information->object_run_list)) ){
            /* 当前心跳，大于等于最小定时间隔，时间到 */
            if(etf_next_expiration <= etf_clock_count){
                /* 执行定时器处理程序 */
                etf_timer_run_flag                                      = 1;
            }
        }
    }
}

/**
 * 获取心跳计数
 *
 *@param :
 *
 *@return:  当前心跳计数值
 *
 *@note  : 
 *
 *
 */
clock_time_t etf_timer_get_clock(void){
    return etf_clock_count;
}

/**
 * 重新设置心跳计数
 *
 *@param :  需要设置的心跳值
 *
 *@return:  
 *
 *@note  : 
 *
 *
 */
void etf_timer_set_clock(clock_time_t m_tick){
    
    etf_clock_count                                                     = m_tick;
}

/**
 * 获取最近的定时到达时间
 *
 *@param :
 *
 *@return:
 *
 *@note  : 
 *
 *
 */
clock_time_t etf_timer_get_next_expiration(void){
    clock_time_t                            now;
	clock_time_t							temp;
	
	ETF_IRQ_DISABLE( );
	
    now																	= etf_timer_get_clock();
	
	if(etf_next_expiration < now){
		temp															= 0;
	} else {
		temp															= etf_next_expiration != 0 ? etf_next_expiration-now : clock_time_t_max;
	}
	
	ETF_IRQ_ENABLE( );
	
    return temp;
}

/**
 * 定时器链表更新
 *
 *@param :
 *
 *@return:
 *
 *@note  : 
 *
 *
 */
static void etf_timer_update(void){
    struct etf_object_information *         information;
    clock_time_t                            now, dist;
    struct etf_list_node *                  node;
    etf_timer_t                             timer_node;

    ETF_IN_ASSERT(ETF_NULL != timer_information);
    
    /* 在对象容器中查找到相应类型对象的链表头 */
    information                                     = timer_information;
    
    if( etf_list_isempty(&(information->object_run_list)) ){
        /* 链表为空 */
        etf_next_expiration                         = 0;
    } else {
        now                                         = etf_timer_get_clock();   
        node                                        = information->object_run_list.next;
        timer_node                                  = (etf_timer_t)etf_list_entry(node, struct etf_object, list);
        dist                                       	= timer_node->start_v + timer_node->interval_v - now;
        
        for(node = information->object_run_list.next; node != &(information->object_run_list); node = node->next){
            /* 获取节点对象 */
            timer_node                              = (etf_timer_t)etf_list_entry(node, struct etf_object, list);
            if( (timer_node->start_v + timer_node->interval_v - now) < dist ){
                dist                               	= timer_node->start_v + timer_node->interval_v - now;
            }
        }

        etf_next_expiration                         = now + dist;
    }
}


/**
 * 设置定时器定时时间，普通回调定时器
 *
 *@param :  timer       ：定时器控制结构指针；
 *          tim         ：定时时间；
 *          type        ：定时器类型，单次、周期；
 *          callback    ：回调函数；
 *
 *@return:  结果；
 *
 *@note  : 
 *  新创建的定时器第一次传入的name参数会被设置到对象中
 *  之后传输的name不会被响应，可以传入ETF_NULL；
 *
 */
etf_err_t etf_ctimer_set(char *name, etf_timer_t timer, clock_time_t tim, etf_timer_type_e type, etf_ctimer_fun_t callback){

    struct etf_object_information *         information;

    ETF_IN_ASSERT(ETF_NULL != timer_information);
    ETF_IN_ASSERT(ETF_NULL != callback);
    ETF_IN_ASSERT(ETF_NULL != timer);
    ETF_IN_ASSERT(0 != tim);
    
    /* 在对象容器中查找到相应类型对象的链表头 */
    information                                     = timer_information;

    /* 设置参数 */
    timer->c_callback                               = callback;
#if ETF_COROUTINE_EN
    timer->e_callback                               = ETF_NULL;
#endif
    timer->interval_v                               = tim;
    timer->type                                     = type;
    
    /* 当前定时器节点状态 */
    switch(etf_object_get_state(&(timer->parent))){

    case    ETF_Object_list_state_run_list          :
        /* 在定时器运行链表中 */
    case    ETF_Object_list_state_suspend_list      :
        /* 在定时器挂起链表中 */
        ETF_IRQ_DISABLE();
        etf_object_detach(&(timer->parent));
        ETF_IRQ_ENABLE();
        //插入到挂起队列
        ETF_LIST_INSERT_BEFORE_SUSPEND_LIST(information, (&(timer->parent)) );
    break;

    default                                         :
        /* 未初始化，未插入到定时器链表中 */
        etf_object_init(&(timer->parent), ETF_Object_Class_Timer, name);
    break;
    }
    
    return ETF_EOK;
}

/**
 * 设置定时器定时时间，事件定时器
 *
 *@param :  timer       ：定时器控制结构指针；
 *          tim         ：定时时间；
 *          type        ：定时器类型，单词、周期；
 *          callback    ：回调协程；
 *
 *@return:  结果；
 *
 *@note  : 
 *
 *
 */
#if ETF_COROUTINE_EN

etf_err_t etf_etimer_set(char *name, etf_timer_t timer, clock_time_t tim, etf_timer_type_e type, etf_etimer_fun_t callback){

    struct etf_object_information *         information;

    ETF_IN_ASSERT(ETF_NULL != timer_information);
    ETF_IN_ASSERT(ETF_NULL != timer);
    ETF_IN_ASSERT(0 != tim);
    
    /* 在对象容器中查找到相应类型对象的链表头 */
    information                                     = timer_information;

    timer->c_callback                               = ETF_NULL;
    timer->e_callback                               = callback;
    timer->interval_v                               = tim;
    timer->type                                     = type;
    
    /* 当前定时器节点状态 */
    switch(etf_object_get_state(&(timer->parent))){

    case    ETF_Object_list_state_run_list          :
        /* 在定时器运行链表中 */
    case    ETF_Object_list_state_suspend_list      :
        /* 在定时器挂起链表中 */
        ETF_IRQ_DISABLE();
        etf_object_detach(&(timer->parent));
        ETF_IRQ_ENABLE();
        //插入到挂起队列
        ETF_LIST_INSERT_BEFORE_SUSPEND_LIST(information, (&(timer->parent)) );
    break;

    default                                         :
        /* 未初始化，未插入到定时器链表中 */
        etf_object_init(&(timer->parent), ETF_Object_Class_Timer, name);
    break;
    }
	
    return ETF_EOK;
}

#endif


/**
 * 开启定时器
 *
 *@param :  timer：定时器控制结构指针；
 *
 *@return:  结果；
 *
 *@note  : 
 *
 *
 */
etf_err_t etf_timer_start(etf_timer_t timer){

//    struct etf_object_information *         information;
    
    ETF_IN_ASSERT( ETF_NULL != timer);
    ETF_IN_ASSERT( ETF_NULL != timer_information);
    
    if(0 == timer->interval_v){
        /* 定时间隔为0，返回错误 */
        return (-ETF_ERROR);
    }
    
    if(ETF_Object_list_state_suspend_list != etf_object_get_state(&(timer->parent))){
        /* 不在挂起链表中，返回错误 */
        return (-ETF_ERROR);
    }

    /* 在对象容器中查找到相应类型对象的链表头 */
//    information                                     = timer_information;
    /* 设置开始时间 */
    timer->start_v                                  = etf_timer_get_clock();
    /* 插入到运行链表 */
    etf_object_change_to_run_list(&(timer->parent));
//    ETF_LIST_INSERT_AFTER_RUN_LIST(information, (&(timer->parent)) );

    /* 更新定时器列表 */
	etf_timer_update();
	
	return ETF_EOK;
}

/**
 * 停止定时器
 *
 *@param :  timer：定时器控制结构指针；
 *
 *@return:  结果；
 *
 *@note  : 
 *
 *
 */
etf_err_t etf_timer_stop(etf_timer_t timer){
    etf_err_t                               res     = ETF_EOK;
    ETF_IN_ASSERT( ETF_NULL != timer);

    if(ETF_Object_list_state_run_list == etf_object_get_state(&(timer->parent))){

        res                                         = etf_object_change_to_suspend_list(&(timer->parent));
        /* 更新定时器列表 */
        etf_timer_update();
    }

    return res;
}

/**
 * 重启定时器
 *
 *@param :  timer：定时器控制结构指针；
 *
 *@return:  结果；
 *
 *@note  : 
 *
 *
 */
etf_err_t etf_timer_restart(etf_timer_t timer){
    enum etf_object_list_state_type         type;
    struct etf_object_information *         information;

    ETF_IN_ASSERT(ETF_NULL != timer_information);
    ETF_IN_ASSERT( ETF_NULL != timer);

    type                                            = etf_object_get_state(&(timer->parent));
    if( (ETF_Object_list_state_run_list == type) || (ETF_Object_list_state_suspend_list == type) ){
        /* 在对象容器中查找到相应类型对象的链表头 */
        information                                 = timer_information;
    
        ETF_IRQ_DISABLE(); 
        /* 删除节点 */
        etf_object_detach(&(timer->parent));
        ETF_IRQ_ENABLE();
        /* 设置开始时间 */
        timer->start_v                              = etf_timer_get_clock();
        /* 插入到运行链表中,链表尾 */
        ETF_LIST_INSERT_BEFORE_RUN_LIST(information, (&(timer->parent)) );
        /* 更新定时器列表 */
        etf_timer_update();
        return ETF_EOK;
    } else {
        return (-ETF_ERROR);
    }

}

/**
 * 定时器处理运行
 *
 *@param :
 *
 *@return:
 *
 *@note  : 
 *
 *
 */
void etf_timer_run(void){

    struct etf_object_information *         information;
    clock_time_t                            now, dist;
    struct etf_list_node *                  node;
    etf_timer_t                             timer_node;


    /* 在对象容器中查找到相应类型对象的链表头 */
    information                                     = timer_information;
        
    if(ETF_NULL == information){
        return;
    }
    
    if(1 == etf_timer_run_flag){

again:
        /* 遍历链表 */
        for(node = information->object_run_list.next; node != &(information->object_run_list); node = node->next){
            /* 获取节点对象 */
            timer_node                              = (etf_timer_t)etf_list_entry(node, struct etf_object, list);
            now                                     = etf_timer_get_clock();
            dist                                    = now - timer_node->start_v + 1;
            if( timer_node->interval_v < dist ){
                /* 定时时间到达 */

                /* 定时器移除链表 */
                ETF_IRQ_DISABLE();
                etf_object_detach(&(timer_node->parent));
                ETF_IRQ_ENABLE();
                /* 执行动作 */
                if(ETF_NULL != timer_node->c_callback){
                    timer_node->c_callback();
                }
#if ETF_COROUTINE_EN

                if(ETF_NULL != timer_node->e_callback){
                    etf_event_post(timer_node->e_callback, ETF_PROCESS_EVENT_TIMER, (void *)timer_node);
                }
#endif
                if(TIMER_TYPE_PERIOD == timer_node->type){
                    /* 周期定时器，重新设置开始时间 */
                    timer_node->start_v             = etf_timer_get_clock();
                    /* 插入到运行链表中,链表尾 */
                    ETF_LIST_INSERT_BEFORE_RUN_LIST( information, (&(timer_node->parent)) );
                } else {
                    /* 单次定时器，插入到挂起链表 */
                    ETF_LIST_INSERT_BEFORE_SUSPEND_LIST( information, (&(timer_node->parent)) );
                }
                
                /* 更新定时器列表 */
//                etf_timer_update();
                /* 处理完一个超时，在次从头处理，直到没有超时 */
                goto again;
            }
        }
		/* 更新定时器列表 */
	etf_timer_update();
    }
    etf_timer_run_flag                              = 0;
}



